package me.chan.collector;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.summarizingInt;

import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

public class CollectorsDemo {

	public static void main(String[] args) {
		List<Dish> menu = Dish.menu;
		//original 
		//int totalCalories1 = menu.stream().map(Dish::getCalories).reduce(Integer::sum).get();
		//use intstream
		//int totalCalories2 = menu.stream().mapToInt(Dish::getCalories).sum();
		//System.out.println(totalCalories1 == totalCalories2);
		//use collector
		//int totalCalories3 = menu.stream().collect(summingInt(Dish::getCalories));
		//System.out.println(totalCalories2 == totalCalories3);
		//use intSummaryStatistic
		IntSummaryStatistics statistics = menu.stream().collect(summarizingInt(Dish::getCalories));
		System.out.println(statistics);
		//一级分组
		Map<Dish.CaloricLevel, List<Dish>> disheseByCaloricLV = menu.stream().collect(groupingBy(
				d -> {
					if (d.getCalories() <= 400) {
						return Dish.CaloricLevel.DIET;
					} else if (d.getCalories() <= 700) {
						return Dish.CaloricLevel.NORMAL;
					} 
						return Dish.CaloricLevel.FAT;
					}	
				));
			
		System.out.println(disheseByCaloricLV);
		
		//二级分组
		Map<Dish.Type, Map<Dish.CaloricLevel,  List<Dish>>> dishesByCaloricLevel = menu.stream().collect(
				groupingBy(Dish::getType, groupingBy(
							d -> {
								if (d.getCalories() <= 400) {
									return Dish. CaloricLevel.DIET;
								} else if (d.getCalories() <= 700) {
									return Dish.CaloricLevel.NORMAL;
								} else 
									
									return Dish.CaloricLevel.FAT;
							}
						)
				)
		);
		System.out.println(dishesByCaloricLevel);
		
		//how many dishes of each type on the menu
		/*Map<Dish.Type, Long> typesCount = menu.stream().collect(groupingBy(Dish::getType, counting()));
		System.out.println(typesCount);*/
		
		//查找菜单上每种类型最高热量的菜肴
		
		/*Map<Dish.Type, Dish> highestCaloriesDish = menu.stream().collect(
				groupingBy(Dish::getType, collectingAndThen(
						maxBy(comparingInt(Dish::getCalories)), Optional::get)
			));
		System.out.println(highestCaloriesDish);
	
		Map<Dish.Type, Long> sumCaloriesOnMenu  = menu.stream().collect(
			groupingBy(Dish::getType, summingLong(Dish::getCalories))
		);
		System.out.println(sumCaloriesOnMenu);
*/
	/*	
		Map<Dish.Type, Set<Dish.CaloricLevel>> caloricLevelsByType = menu.stream().collect(
						groupingBy(Dish::getType, mapping(
								dish -> {
									if (dish.getCalories() <= 400) return Dish.CaloricLevel.DIET;
									else if (dish.getCalories() <= 700) return Dish.CaloricLevel.NORMAL;
									else return Dish.CaloricLevel.FAT;
								},  //toSet()
								toCollection(HashSet::new)		//customized
					)));
		System.out.println(caloricLevelsByType);
	*/
		//区分荤素：
		/*Map<Boolean, List<Dish>> partitionedMenu = menu.stream().collect(partitioningBy(Dish::isVegetarian));
		List<Dish> vegetarianDish =  partitionedMenu.get(true);
		System.out.println(vegetarianDish);
		*/
		//分区分组
	/*	Map<Boolean, Map<Dish.Type, List<Dish>>> vegetarianDishByType = menu.stream().collect(partitioningBy(Dish::isVegetarian,
				groupingBy(Dish::getType)));
		System.out.println(vegetarianDishByType);
		*/
		//使用自定义收集器
		/*List<Dish> dishes = menu.stream().collect(ArrayList::new, List::add, List::addAll);
		System.out.println(dishes);
		*/
		
		Map<Boolean, List<Integer>> partionPrimesWithCustomCollect = IntStream.rangeClosed(2, 100)
																																.boxed().collect(new PrimeNumbersCollector());
		System.out.println(partionPrimesWithCustomCollect);
		
	}
	
}
